from flask import request, json
from werkzeug.exceptions import HTTPException


class APIException(HTTPException):
    ''' 自定义全局的异常处理类,重写HTTPException的方法和函数
        让新的类返回json格式而非html,全局处理error的手段更灵活
        因为HTTPException实现__call__方法,所以可以当做函数调用
        __call__会将我们重写的body和header写入Response中,我们只要return,或者raise抛出即可'''

    code = 500
    msg = '服务器内部错误'
    error_code = 999 # 我们可以内部定义一状态码,前端可以根据这种状态码判断异常

    def __init__(self, code=None, msg=None, error_code=None, headers=None):
        # 如果需要第二种修改方式,这个构造函数就提供了这样的能力,它让当前类变得更加灵活,支持类在实例化时修改属性
        if code:
            self.code = code
        if msg:
            self.msg = msg
        if error_code:
            self.error_code = error_code
        # 父类的__init__需要response,但父类内部会自己构建响应对象,不需要传入
        super(APIException, self).__init__(msg, None) # TODO 为什么我们不需要传入response呢?HTTPException内部是怎么实现的呢?

    def get_body(self, environ=None):
        body = dict(
            msg=self.msg,
            error_code=self.error_code,
            # TODO 把请求哪一个url错误的信息返回给前段有什么意义呢? 权限管理用到吗?
            # 到2019.6.21号来看我还是想不到有什么用,打印日志吗?
            request=request.method + ' ' + self.get_main_url()
        )
        text = json.dumps(body) # 这里转成json,让异常返回变得更轻,更符合REST风格
        return text

    def get_headers(self, environ=None):
        return [('Content-Type', 'application/json')]

    @staticmethod
    def get_main_url():
        path = request.full_path
        return path.split('?')[0]
